#!/usr/bin/ruby -w
# indent.rb
require 'optparse'
require 'yaml'

module Indent
  class Indenter
    attr_accessor :lang, :extensions, :command

    def initialize(lang, extensions, command)
      @lang = lang
      @extensions = extensions
      @command = command
    end
  end
 
  class Engine
    attr_accessor :verbose

    def initialize(indenters)
      @indenters = indenters
      @verbose = false
    end

    def indent_file(filename)
      fail "file #{filename} doesn't exist" unless File.exist?(filename)

      puts "Processing #{filename}..."
      ext = File.extname(filename)

      indented = false
      @indenters.each { |i|
        next unless i.extensions.include?(ext)
        run_indenter(i, filename)
        indented = true
        break
      }

      puts "No indenter defined for #{ext} files" unless indented
    end

    #######
    private

    def run_indenter(indenter, file)
      command = indenter.command.gsub('{{file}}', file)
      trace `#{command}`
      # puts "#{command}"
    end

    def trace(text)
      puts text if @verbose
    end
  end
end

###############################################################################

if __FILE__ == $0 then
  options = {}

  optparser = OptionParser.new do |opts|
    opts.banner = "Usage: #{__FILE__} [options] file1 file2 ..."

    options[:verbose] = false
    opts.on('-v', '--verbose', 'Output more information') do
      options[:verbose] = true
    end

    options[:configfile] = 'indent.yaml'
    opts.on('-c', '--config FILE', 'Use indenters from FILE (default is indent.yaml)') do |file|
      options[:configfile] = file
    end

    opts.on('-h', '--help', 'Display this screen') do
      puts opts
      puts
      puts 'Examples:'
      puts '- indent all .cpp files found in a directory:'
      puts '  ruby indent.rb some/path/*.cpp'
      puts '- indent all .cpp files found in a directory and its subdirectories:'
      puts '  ruby indent.rb some/path/**/*.cpp'
      puts '- indent all .cpp and .h files found in a directory:'
      puts '  ruby indent.rb some/path/*.cpp some/path/*.h'
      exit
    end
  end

  optparser.parse!

  indenters = []
  configfile = options[:configfile]
  configfile = File.join(File.dirname(__FILE__), configfile) unless File.file?(configfile)

  object = ""
  File.open(configfile, 'r').each { |line|
    if line.start_with?('---')
      unless object == "" then
        indenters << YAML::load(object)
        object = ""
      end
    end
    object += line
  }
  indenters << YAML::load(object)

  engine = Indent::Engine.new(indenters)
  engine.verbose = options[:verbose]

  # puts options
  # puts indenters

  ARGV.each do |arg|
    target = arg.gsub('\\', '/')
    Dir[target].each { |file| engine.indent_file(file) }
  end
end
